package org.dromara.datacheck.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.TemporalAdjusters;
import java.util.*;

/**
 * @Author 刘武贵
 * @Date 2024/9/18 01:03
 * @Description 功能描述：自己需要的定制化的工具类
 */
public class MyUtil {

    /**
     * 根据传进的日期字符串，比如传10，那就构建日期，根据当前时间来，比如当前是2024年，传10就是10月，就构建10月1日到31日的List<String>，里面的值就是10月01日、10月02日，
     * 注意如果日数为10以下的就补0
     *
     * @param monthStr 月份字符串
     * @return 日期字符串集合
     */
    public static List<String> buildDatesForMonth(String monthStr) {
        // 检查输入是否合法
        if (monthStr == null || monthStr.isEmpty() || !monthStr.matches("\\d{1,2}")) {
            throw new IllegalArgumentException("意外的月份字符串: " + monthStr);
        }

        int month = Integer.parseInt(monthStr);
        if (month < 1 || month > 12) {
            throw new IllegalArgumentException("月份必须是1到12之间");
        }

        // 获取当前年份
        int currentYear = LocalDate.now().getYear();

        // 创建 YearMonth 对象
        YearMonth yearMonth = YearMonth.of(currentYear, month);

        // 获取该月的天数
        int daysInMonth = yearMonth.lengthOfMonth();

        // 创建日期格式化器
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");

        // 构建日期列表
        List<String> dates = new ArrayList<>();
        for (int day = 1; day <= daysInMonth; day++) {
            LocalDate date = LocalDate.of(currentYear, month, day);
            dates.add(formatDateStringNoPadZeroByMonth(date.format(formatter)));
        }

        return dates;
    }

    /**
     * 将日期字符串格式化为"年月日"的格式，不补零
     * 例如，输入"2023/08/28"，输出"2023年8月28日"
     *
     * @param dateStr 原始日期字符串，格式为"年/月/日"
     * @return 格式化后的日期字符串，格式为"年月日"
     */
    public static String formatDateStringNoPadZero(String dateStr) {
        // 分割日期字符串
        String[] parts = dateStr.split(" ")[0].split("/");

        // 构造新的日期字符串
        return parts[0] + "年" + parts[1] + "月" + parts[2] + "日";
    }

    /**
     * 将日期字符串格式化为"年月日"的格式，不补零
     * 例如，输入"2023/08/28"，输出"8月28日"
     *
     * @param dateStr 原始日期字符串，格式为"月/日"
     * @return 格式化后的日期字符串，格式为"月日"
     */
    public static String formatDateStringNoPadZeroByMonth(String dateStr) {
        // 分割日期字符串
        String[] parts = dateStr.split(" ")[0].split("/");

        // 构造新的日期字符串
        return parts[1] + "月" + parts[2] + "日";
    }

    /**
     * 将给定的日期字符串格式化为"年月日"的格式，并在月和日前面补零至两位数
     * 此方法主要用于确保数据库中日期的一致性和可读性
     *
     * @param dateStr 原始日期字符串，格式为"YYYY/MM/DD"
     * @return 格式化后的日期字符串，格式为"YYYY年MM月DD日"
     */
    public static String formatDateStringPadZero(String dateStr) {
//        System.out.println("传进来的dateStr:" +dateStr );
        // 分割日期字符串
        String[] parts = dateStr.split(" ")[0].split("/");

        // 构造新的日期字符串
        String year = parts[0];
        String month = padZeroByString(parts[1]);
        String day = padZeroByString(parts[2]);

        return year + "年" + month + "月" + day + "日";
    }

    /**
     * 将给定的日期字符串格式化为"月日"的格式，并在月和日前面补零至两位数
     * 此方法主要用于确保数据库中日期的一致性和可读性
     *
     * @param dateStr 原始日期字符串，格式为"MM/DD"
     * @return 格式化后的日期字符串，格式为"MM月DD日"
     */
    public static String formatDateStringPadZeroByMonth(String dateStr) {
//        System.out.println("传进来的dateStr:" +dateStr );
        // 分割日期字符串
        String[] parts = dateStr.split(" ")[0].split("/");

        // 构造新的日期字符串
        String month = padZeroByString(parts[1]);
        String day = padZeroByString(parts[2]);

        return  month + "月" + day + "日";
    }

    /**
     * 将给定的日期字符串格式化为"年月日"的格式，并在月和日前面补零至两位数
     * 此方法主要用于确保数据库中日期的一致性和可读性
     *
     * @param dateStr 原始日期字符串，格式为"YYYY/MM/DD"
     * @return 格式化后的日期字符串，格式为"YYYY年MM月DD日"
     */
    public static String formatDateStringNoPadZero2(String dateStr) {
        // 分割日期字符串
        String[] parts = dateStr.split(" ")[0].split("-");

        // 构造新的日期字符串
        String year = parts[0];
        String month = padZeroByString(parts[1]);
        String day = padZeroByString(parts[2]);

        return year + "年" + month + "月" + day + "日";
    }

    /**
     * 在数字字符串前补零
     * 如果数字小于10，则在数字前添加一个'0'；否则直接返回原数字字符串
     *
     * @param number 数字字符串，表示要处理的数字
     * @return 处理后的数字字符串，保证数字小于10时前面有零
     */
    public static String padZeroByString(String number) {
        if (Integer.parseInt(number) < 10) {
            return "0" + number;
        } else {
            return number;
        }
    }

    /**
     * 将指定格式的日期字符串解析为LocalDate对象
     *
     * @param dateStr 日期字符串，格式为"yyyy/MM/dd"
     * @return 解析后的LocalDate对象
     */
    public static LocalDate parseToLocalDate(String dateStr) {
        return LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("yyyy/MM/dd"));
    }

    /**
     * 根据LocalDate对象格式化日期字符串
     * 该方法将日期格式化为"年-月-日"的形式，其中月和日会在个位数前补零
     *
     * @param date LocalDate对象，表示输入的日期
     * @return 格式化后的日期字符串，例如"2023年04月01日"
     */
    public static String formatDateStringByLocalDate(LocalDate date) {
        int year = date.getYear();
        int month = date.getMonthValue();
        int day = date.getDayOfMonth();

        return year + "年" + padZeroByInt(month) + "月" + padZeroByInt(day) + "日";
    }

    /**
     * 将小于10的整数前面补充0，大于等于10的整数直接转换为字符串
     *
     * @param number 需要处理的整数
     * @return 处理后的字符串
     */
    public static String padZeroByInt(int number) {
        if (number < 10) {
            return "0" + number;
        } else {
            return String.valueOf(number);
        }
    }

    /**
     * 根据提供的日期字符串列表构建一个映射，其中列表中的每个日期对应一个键值对。
     * 键是由'date'前缀和列表中日期的索引组成的字符串，值是格式化后的日期字符串。
     * 形如<date1,日期>的key value对
     *
     * @param formattedDateList 包含格式化后日期字符串的列表，不能为空。
     * @return 返回一个按插入顺序保存的映射，其中键是'dateN'形式的字符串（N是索引），值是对应的日期字符串。
     */
    public static Map<String, String> buildDateMap(List<String> formattedDateList) {
        // 创建一个链接哈希映射来保持元素的插入顺序
        Map<String, String> dateMap = new LinkedHashMap<>();

        // 初始化索引值
        int index = 1;
        // 遍历日期字符串列表
        for (String date : formattedDateList) {
            // 为每个日期生成键名，格式为'date1', 'date2', ...
            String key = "date" + index;
            // 将键值对添加到映射中
            dateMap.put(key, date);
            // 更新索引值
            index++;
        }

        // 返回构建好的日期映射
        return dateMap;
    }

    /**
     * 将日期字符串转换为指定格式的日期对象
     *
     * @param dateString 日期字符串，如 "2024/9/25"
     * @return 转换后的日期对象，格式为 "yyyy-MM-dd 00:00:00"
     */
    public static LocalDateTime parseAndFormatDate(String dateString) {
        if (dateString == null || dateString.isEmpty()) {
            return null;
        }

        List<String> datePatterns = Arrays.asList(
            "yyyy/MM/dd",
            "yyyy/M/d",
            "yyyy-MM-dd",
            "yyyy-M-d"
        );

        for (String pattern : datePatterns) {
            try {
                DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern(pattern);
                LocalDateTime dateTime = LocalDateTime.parse(dateString, inputFormatter);

                // 设置时分秒为 00:00:00
                return dateTime.withHour(0).withMinute(0).withSecond(0);
            } catch (DateTimeParseException ignored) {
                // 继续尝试下一个日期格式
            }
        }

        // 如果所有格式都无法解析，则尝试手动格式化
        try {
            String formattedDateString = formatDateString(dateString);
            DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
            LocalDateTime dateTime = LocalDateTime.parse(formattedDateString, outputFormatter);

            return dateTime;
        } catch (Exception e) {
            // 处理解析异常
            e.printStackTrace();
            System.out.println("无法解析日期：" + dateString);
            return null;
        }
    }

    /**
     * 将日期字符串转换为指定格式的日期对象
     *
     * @param dateString 日期字符串，如 "2024/9/25"
     * @return 转换后的日期对象，格式为 "yyyy-MM-dd 00:00:00"
     */
    public static Date parseAndFormatDate2(String dateString) {
        Date newDate = null;
        if (dateString == null || dateString.isEmpty()) {
            return null;
        }

        List<String> datePatterns = Arrays.asList(
            "yyyy/MM/dd",
            "yyyy/M/d",
            "yyyy-MM-dd",
            "yyyy-M-d"
        );

        // 设置时区为 UTC
        TimeZone timeZone = TimeZone.getTimeZone("UTC");

        for (String pattern : datePatterns) {
            try {
                SimpleDateFormat inputFormatter = new SimpleDateFormat(pattern);
                inputFormatter.setTimeZone(timeZone); // 设置输入解析器的时区

                Date date = inputFormatter.parse(dateString);

                // 设置时分秒为 00:00:00
                SimpleDateFormat outputFormatter = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
                outputFormatter.setTimeZone(timeZone); // 设置输出格式器的时区

                String formattedDate = outputFormatter.format(date);
                newDate = outputFormatter.parse(formattedDate);
                break; // 成功解析后退出循环
            } catch (ParseException ignored) {
                // 继续尝试下一个日期格式
            }
        }
        return newDate;
    }

    private static String formatDateString(String dateString) {
        String[] parts = dateString.split("/");
        if (parts.length != 3) {
            throw new IllegalArgumentException("日期格式错误：" + dateString);
        }

        String year = parts[0];
        String month = parts[1].length() == 1 ? "0" + parts[1] : parts[1];
        String day = parts[2].length() == 1 ? "0" + parts[2] : parts[2];

        return year + "/" + month + "/" + day + " 00:00:00";
    }

    /**
     * 将形如 "2024/9/1 23:33:13" 的日期字符串转换为 LocalDateTime 类型。
     *
     * @param dateString 日期字符串
     * @return 转换后的 LocalDateTime 对象
     * @throws DateTimeParseException 如果解析失败则抛出此异常
     */
    public static LocalDateTime convertDateStringToLocalDateTime(String dateString) throws DateTimeParseException {
        // 替换 "/" 为 "-"
        String formattedDate = dateString.replace("/", "-");

        // 定义输入的日期格式
        DateTimeFormatter inputFormat = DateTimeFormatter.ofPattern("yyyy-M-d H:m:s");

        // 解析日期字符串
        LocalDateTime dateTime = LocalDateTime.parse(formattedDate, inputFormat);

        return dateTime;
    }

    /**
     * 将形如 "2024/9/1 23:33:13" 的日期字符串转换为 Date 类型。
     *
     * @param dateString 日期字符串
     * @return 转换后的 Date 对象
     * @throws ParseException 如果解析失败则抛出此异常
     */
    public static Date convertDateString(String dateString) throws ParseException {
        // 替换 "/" 为 "-"
        String formattedDate = dateString.replace("/", "-");

        // 定义输入和输出的日期格式
        SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-M-d H:m:s");
        SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // 解析日期字符串
        Date date = inputFormat.parse(formattedDate);

        // 可选：重新格式化日期字符串（如果需要的话）
        // String formattedString = outputFormat.format(date);

        return date;
    }
    public static String formatDateStringByJst(String dateTimeStr) {
        // 找到空格的位置
        int spaceIndex = dateTimeStr.indexOf(' ');
        if (spaceIndex != -1) {
            // 截取从开头到空格位置的子串
            String datePart = dateTimeStr.substring(0, spaceIndex);

            // 去掉月份和日期中的前导零
            String formattedDate = datePart.replace("/0", "/");
            return formattedDate;
        }
        // 如果没有找到空格，返回原字符串
        return dateTimeStr;
    }

    /**
     * 构建指定月份的日期范围
     * 此方法用于创建一个包含指定月份的第一天和最后一天日期的映射
     * 主要用于需要按月统计或查询的场景，提供了一个简单的方式获取月份的起始和结束日期
     *
     * @param monthString 表示月份的字符串，需要转换为整数以使用
     * @return 返回一个映射，包含指定月份的开始日期和结束日期
     */
    public static Map<String, LocalDate> buildDateRange(String monthString) {
        // 检查传入的月份字符串是否为空，为空则抛出异常
        if (monthString == null || monthString.isEmpty()) {
            throw new IllegalArgumentException("月份字符串不能为空");
        }
        // 将传入的月份字符串转换为整数，以便使用
        int month = Integer.parseInt(monthString);
        // 获取当前日期，用于确定年份
        LocalDate now = LocalDate.now();
        int year = now.getYear();

        // 构建指定月份的第一天日期
        LocalDate startDate = LocalDate.of(year, month, 1);
        // 构建指定月份的最后一天日期
        LocalDate endDate = LocalDate.of(year, month, 1).with(TemporalAdjusters.lastDayOfMonth());

        // 创建一个映射，用于存储日期范围
        Map<String, LocalDate> dateRange = new HashMap<>();
        // 将起始日期和结束日期存入映射中
        dateRange.put("startDate", startDate);
        dateRange.put("endDate", endDate);

        // 返回包含日期范围的映射
        return dateRange;
    }

}
